﻿using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Configuration.Assemblies;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace CAD.LoadX
{
    public class CommandHotLoad
    {

        static string assemblyPath = Assembly.GetExecutingAssembly().Location;
        static string assemblyDir = Path.GetDirectoryName(assemblyPath) + "\\";
        //static string assemblyDir = "D:\\WORKSPACE\\CODE_CAD\\CAD.Demo\\bin\\Debug\\";
        Assembly assemblyJson = Assembly.LoadFrom($"{assemblyDir}Newtonsoft.Json.dll");

        [CommandMethod("DDEE")]
        public void HotLoadDll()
        {

            //编辑器
            Editor editor = Application.DocumentManager.MdiActiveDocument.Editor;

            #region  读取json
            string jsonPath = $"{assemblyDir}debugInfo.json";
            editor.WriteMessage($"\n dll-path:{jsonPath} \n ");//命令行文字
            if (!File.Exists(jsonPath))
            {
                editor.WriteMessage("debug json not exist");
                return;
            }

            string jsonStr = jsonPath.ReadFileText(Encoding.UTF8);
            CmdInfo cmdInfo = jsonStr.ToEntity<CmdInfo>().First();


            string dllName = cmdInfo.dllName;
            string namespaceName = cmdInfo.namespaceName;
            string className = cmdInfo.className;
            string methodName = cmdInfo.methodName; 
            #endregion


            #region  fix 反射方法 通过类和方法名称 获得功能DLL内实体的方法实例

            var dllPath = $"{assemblyDir}{dllName}";
            var namespaceClass = $"{namespaceName}.{className}";

            //var guid = Guid.NewGuid();
            //File.Copy(dllPath, $"{dllPath}{guid}", true);
            //dllPath = $"{dllPath}{guid}";

            Action command = GenCommandAction(dllPath, namespaceClass, methodName);
            try
            {
                command?.Invoke();
            }
            catch (System.Exception ex)
            {
                System.Windows.MessageBox.Show(ex.Message, "error++");
            }

            #endregion

        }

        /// <summary>
        /// 反射获得所需执行
        /// </summary>
        /// <param name="dllPath"> dll文件路径  C:\\CAD\\bin\\Debug\\SEPD.CadDemo.Space.dll</param>
        /// <param name="pathToClass">命名空间和类的全称 SEPD.CadDemo.Space.Class</param>
        /// <param name="methodName"> 执行方法名  methodName</param>
        /// <returns></returns>
        public static Action GenCommandAction(string dllPath, string pathToClass, string methodName, object[] constuctParams = null)
        {
            var targetAssembly = Assembly.Load(File.ReadAllBytes(dllPath));
            var targetType = targetAssembly.GetType(pathToClass);
            var targetMethod = targetType.GetMethod(methodName);
            var targetObject = Activator.CreateInstance(targetType);

            if (constuctParams == null) { constuctParams = new object[] { }; }
            Action cmd = () => targetMethod.Invoke(targetObject, constuctParams);

            return cmd;

        }

    }

    public class CmdInfo
    {
        public string buttonName { get; set; }
        public string buttonDescription { get; set; }

        public string dllName { get; set; }
        public string namespaceName { get; set; }
        public string className { get; set; }
        public string methodName { get; set; }
    }

    public static class JsonOperator
    {
        public static string ReadFileText(this string jsonFile, Encoding encoding)
        {
            try
            {
                string text = "";
                FileStream fs = new FileStream(jsonFile, FileMode.Open, FileAccess.Read);
                using (StreamReader file = new StreamReader(fs, encoding))
                {
                    text = file.ReadToEnd();
                }
                return text;
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.ToString());
                return null;
            }
        }

        /// <summary>
        /// 适用于 最外层为列表或者单体的json文档读取  
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="jsonData"></param>
        /// <param name="settings"></param>
        /// <returns></returns>
        public static IList<T> ToEntity<T>(this string jsonData, JsonSerializerSettings settings = null) where T : class
        {
            IList<T> results = new List<T>();
            object obj = JsonConvert.DeserializeObject(jsonData, settings);
            if (obj is JArray)
            {
                JArray jArray = JArray.Parse(jsonData);
                foreach (var arr in jArray)
                {
                    results.Add(JsonConvert.DeserializeObject<T>(arr.ToString()));
                }
            }
            else
            {
                results.Add(JsonConvert.DeserializeObject<T>(jsonData, settings));
            }
            return results;
        }

    }


}
